package com.yhb.channel.impl.BJCJ.http;

import com.alibaba.fastjson.JSONObject;
import com.yhb.channel.impl.BJCJ.BJCJChannel;
import com.yhb.channel.impl.BJCJ.BJCJConfig;
import com.yhb.channel.impl.BJCJ.BJCJException;
import com.yhb.channel.impl.BJCJ.http.Request.base.BJCJBaseRequest;
import com.yhb.channel.impl.BJCJ.http.utils.*;
import com.yhb.channel.provider.IUtilProvider;
import com.yhb.channel.utils.ChannelDateUtil;
import com.yhb.channel.utils.ChannelJSONUtil;
import com.yhb.channel.utils.ChannelLogger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
public class BJCJClient {
    @Autowired
    private IUtilProvider iUtilProvider;
    @Autowired
    private BJCJConfig bjcjConfig;

    private String sysId;
    private String privateKey;
    private static ChannelLogger logger;

//    public static final String BASE_REQ_URL_FOR_MERCHANT
//            = "http://test.trading.anlvtech.com/merchant/";
//    public static final String BASE_REQ_URL_FOR_TRANSACTION
//            = "http://test.trading.anlvtech.com/transaction/";

    public static final String BASE_REQ_URL_FOR_MERCHANT
            = "http://trading.anlvtech.com/merchant/";
    public static final String BASE_REQ_URL_FOR_TRANSACTION
            = "http://trading.anlvtech.com/transaction/";

    // 商户操作类接口
    public static final List<String> MERCHANT_ACTIONS = Arrays.asList(
            "addMerInf",
            "bindcardSms",
            "bindcardconfirm",
            "walletQuery",
            "updateMerInf",
            "bindcardQuery"
    );

    // 商户交易类接口
    public static final List<String> TRANSACTION_ACTIONS = Arrays.asList(
            "merchantConsume",
            "merchantConsumeConfim",
            "consumeQuery",
            "merchantWithdraw",
            "withdrawQuery",
            "ysRefund"
    );

    // 敏感字段
    public static final String[] SENSITIVE_FIELD = {
            "bankAccountNo",
            "idCardNo",
            "mobile",
            "cvn2",
            "expired"
    };

    @PostConstruct
    private void init() {
       this.sysId = bjcjConfig.getSysId();
       this.privateKey = bjcjConfig.getPrivateKey();
       logger = new ChannelLogger(BJCJChannel.CHANNEL_BASE_NAME, BJCJException.class, iUtilProvider);
    }

    private void saveRequestFlow(String flow, String channelCode) {
        iUtilProvider.savePayChannelFlow(BJCJChannel.CHANNEL_BASE_NAME + "-" + channelCode + "---", flow);
    }

    private void logRequest(String method, String requestId, String req, String channelCode) {
        String flow = method + "::" + requestId + "::" + "\n请求包 ==> " + req;
        logger.info(flow);
        saveRequestFlow(flow, channelCode);
    }

    private void logResponse(String method, String requestId, String res, String channelCode) {
        String flow = method + "::" + requestId + "::" + "\n回包 ==> " + res;
        logger.info(flow);
        saveRequestFlow(flow, channelCode);
    }

    public HashMap<String, String> generateHashMap(BJCJBaseRequest request) {
        return ChannelJSONUtil.jsonToMap(ChannelJSONUtil.toJson(request));
    }

    public void encrypt(HashMap<String, String> map, String privateKey) {
        // 处理敏感字段加密
        for (String key : SENSITIVE_FIELD) {
            if (map.containsKey(key)) {
                String val = map.get(key);
                map.remove(key);
                String tmpArr = BJCJAESUtil.encrypt(val, privateKey);
                map.put(key, tmpArr);
            }
        }
//        logger.info("加密完成： ——————————————");
//        logger.info("map: " + ChannelJSONUtil.toJson(map));
    }

    public <T> T http(String action, BJCJBaseRequest request, Class<T> responseType, String channelCode) {
        logger.info( channelCode + "开始请求 ---------------------------" + action);
        // 发请求
        String baseUrl = MERCHANT_ACTIONS.contains(action) ? BASE_REQ_URL_FOR_MERCHANT : BASE_REQ_URL_FOR_TRANSACTION;

        // 预处理和加密
        HashMap<String, String> map = this.generateHashMap(request);
        this.encrypt(map, privateKey);

        // 拼装JSONObject
        JSONObject paramsJsonObj = new JSONObject();
        for (String key : map.keySet()) {
            paramsJsonObj.put(key, map.get(key));
        }

        // 排序
        String sortJsonValueToStr = BJCJSortUtil.sortJsonValueToStr(paramsJsonObj, "sign");
//        logger.info("排序完毕: " + sortJsonValueToStr);
        // 签名
        String sign = BJCJSignUtil.getSHA256StrJava(sortJsonValueToStr + privateKey);
        JSONObject signJson = new JSONObject();
        signJson.put("sysId", sysId);
        signJson.put("sign", sign);
        String param = BJCJJsonUtil.object2Json(paramsJsonObj);
//        logger.info("请求参数: " + param);
        logRequest(action, request.getReqFlowNo(), param, channelCode);

//        logger.info("签名头: " + signJson.toJSONString());
//        Date now = new Date();
//        logger.info("请求时间：" + ChannelDateUtil.getDateString(now,
//                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));

        String sendPostJsons = BJCJHttpRequest.sendPostJsons(baseUrl + action, signJson, param);
        logResponse(action, request.getReqFlowNo(), sendPostJsons, channelCode);
        return ChannelJSONUtil.parseJson(sendPostJsons, responseType);
    }
}
